package lbldy

import (
	"fmt"
	"github.com/astaxie/beego/logs"
	"gopkg.in/mgo.v2/bson"
	"imovie_collect/utils"
	"regexp"
	"strings"
	"sync"

	"github.com/PuerkitoBio/goquery"

	"imovie_collect/lib/mdb"
	"imovie_collect/models"
)

var SpaceReg *regexp.Regexp

type Lbldy struct {
	sess *mdb.MdbSession
}

func NewLbldy(sess *mdb.MdbSession) *Lbldy {
	return &Lbldy{
		sess: sess,
	}
}

func (l *Lbldy) Run(kind int) {
	wg := new(sync.WaitGroup)
	movieUrlChan := make(chan string, 10)
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(movieUrlChan <-chan string) {
			for movieUrl := range movieUrlChan {
				movie, err := l.getItem(movieUrl, kind)
				if err != nil {
					logs.Warn("get item err:%s", err.Error())
					continue
				}

				logs.Debug("%s %s", movie.Id, movie.Name)
				if err := l.saveMovie(movie); err != nil {
					logs.Warn("save movie err:%s", err.Error())
				}
			}
		}(movieUrlChan)
	}

	for page := 0; page < 660; page++ {
		l.getMovieUrl(page, kind, movieUrlChan)
	}
	return
}

func (l *Lbldy) getPageUrl(page, kind int) string {
	var kindStr string
	if kind == 2 {
		kindStr = "television"
	} else {
		kindStr = "movie"
	}

	return fmt.Sprintf("http://www.lbldy.com/%s/page/%d/", kindStr, page)
}

func (l *Lbldy) getMovieUrl(page int, kind int, movieUrlChan chan<- string) {
	queryUrl := l.getPageUrl(page, kind)
	doc, err := goquery.NewDocument(queryUrl)
	if err != nil {
		return
	}

	doc.Find("div.postlist h4 a").Each(func(index int, sel *goquery.Selection) {
		link, exists := sel.Attr("href")
		if !exists {
			return
		}
		movieUrlChan <- strings.TrimSpace(link)
	})
}

func (l *Lbldy) saveMovie(movie *models.Longdy) error {
	return l.sess.Upsert(movie.Topic(), bson.M{"_id": movie.Id}, bson.M{"$set": movie})
}

func (l *Lbldy) getItem(itemUrl string, kind int) (item *models.Longdy, err error) {
	id := l.getIdbyUrl(itemUrl)
	if id == "" {
		err = fmt.Errorf("id为空")
		return
	}

	doc, err := goquery.NewDocument(itemUrl)
	if err != nil {
		return
	}

	item = new(models.Longdy)
	item.Id = id
	item.Type = kind
	item.Name = strings.TrimSpace(doc.Find(fmt.Sprintf("#post-%s > h2", id)).Text())
	item.Intro = strings.TrimSpace(doc.Find(fmt.Sprintf("#post-%s > div.entry > p:nth-child(1)", id)).Text())
	item.Addrs = make([]*models.Addr, 0, 10)
	doc.Find(fmt.Sprintf("#post-%s > div.entry > p", id)).Each(func(index int, sel *goquery.Selection) {
		dlUrl, exists := sel.Find("a").Attr("href")
		if !exists {
			return
		}

		if ok, kind := l.matchDownloadLink(dlUrl); ok {
			note := utils.TrimeSpace(sel.Text())
			item.Addrs = append(item.Addrs, &models.Addr{
				Url:  dlUrl,
				Note: note,
				Type: kind,
			})
		}
	})

	if len(item.Addrs) == 0 {
		doc.Find(fmt.Sprintf("#post-%s > div.entry > ol > li", id)).Each(func(index int, sel *goquery.Selection) {
			dlUrl, exists := sel.Find("a").Attr("href")
			if !exists {
				return
			}

			if ok, kind := l.matchDownloadLink(dlUrl); ok {
				note := utils.TrimeSpace(sel.Text())
				item.Addrs = append(item.Addrs, &models.Addr{
					Url:  dlUrl,
					Note: note,
					Type: kind,
				})
			}
		})
	}

	return
}

var dlTypeMap map[string]int = map[string]int{
	"magnet:?xt=":          1,
	".torrent":             2,
	"ed2k://":              3,
	"thunder://":           4,
	"http://pan.baidu.com": 5,
}

func (l *Lbldy) matchDownloadLink(dlUrl string) (bool, int) {
	if dlUrl == "" {
		return false, 0
	}

	for key, kind := range dlTypeMap {
		if strings.Index(dlUrl, key) == 0 || strings.LastIndex(dlUrl, key) == len(dlUrl)-len(key)-1 {
			return true, kind
		}
	}

	return false, 0
}

func (l *Lbldy) getIdbyUrl(itemUrl string) (number string) {
	// http://movie.mtime.com/12281/
	numberReg, err := regexp.Compile("[^\\D][\\d]*")
	if err != nil {
		return
	}

	number = numberReg.FindString(itemUrl)
	return
}
